﻿module DomainTypeActionInvoke26
open NUnit.Framework
open RestfulObjects.Mvc
open NakedObjects.Surface
open System.Net
open System.Net.Http
open System.Net.Http.Headers
open System.IO
open Newtonsoft.Json.Linq
open System.Web
open System
open RestfulObjects.Snapshot.Utility 
open RestfulObjects.Snapshot.Constants
open System.Web.Http
open System.Collections.Generic
open System.Linq
open RestTestFunctions
// open System.Json

let VerifyResult result resultValue oType oRel ooType ooRel = 
       let jsonResult = readSnapshotToJson result
       let parsedResult = JObject.Parse(jsonResult)

       let rurl = sprintf "http://localhost/domain-types/%s" ooType 
       let args = TObjectJson([TProperty(ooRel, TObjectJson([TProperty(JsonPropertyNames.Href, TObjectVal(rurl))]))])

       let expected = [ TProperty(JsonPropertyNames.Id, TObjectVal(oRel));
                        TProperty(JsonPropertyNames.Value, TObjectVal(resultValue));
                        TProperty(JsonPropertyNames.Links, TArray([ TObjectJson( TProperty(JsonPropertyNames.Arguments, args) :: makeGetLinkProp RelValues.Self (sprintf "domain-types/%s/type-actions/%s/invoke" oType oRel)  RepresentationTypes.TypeActionResult "") ]));
                        TProperty(JsonPropertyNames.Extensions, TObjectJson([]) ) ]
    
       Assert.AreEqual(HttpStatusCode.OK, result.StatusCode)
       Assert.AreEqual(new typeType(RepresentationTypes.TypeActionResult), result.Content.Headers.ContentType)
       assertNonExpiringCache result 
       compareObject expected parsedResult
 
let GetIsSubTypeOfReturnFalseSimpleParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.MostSimple"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSubtypeOf"
        let ooRel = JsonPropertyNames.SuperType
        let resultValue = false; 
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs

        let args = CreateArgMapFromUrl qs

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        
        VerifyResult result resultValue oType oRel ooType ooRel

let GetIsSuperTypeOfReturnFalseSimpleParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.MostSimple"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSupertypeOf"
        let ooRel = JsonPropertyNames.SubType
        let resultValue = false;
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs

        let args = CreateArgMapFromUrl qs

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        VerifyResult result resultValue oType oRel ooType ooRel
 
let GetIsSubTypeOfReturnTrueSimpleParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.WithActionObject"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSubtypeOf"
        let ooRel = JsonPropertyNames.SuperType
        let resultValue = true
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs

        let args = CreateArgMapFromUrl qs

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        VerifyResult result resultValue oType oRel ooType ooRel
 
let GetIsSuperTypeOfReturnTrueSimpleParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.WithAction"
        let ooType = ttc "RestfulObjects.Test.Data.WithActionObject"
        let oRel = "isSupertypeOf"
        let ooRel = JsonPropertyNames.SubType
        let resultValue = true
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs

        let args = CreateArgMapFromUrl qs

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        VerifyResult result resultValue oType oRel ooType ooRel

let GetIsSubTypeOfReturnFalseFormalParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.MostSimple"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSubtypeOf"
        let ooRel = JsonPropertyNames.SuperType
        let resultValue = false; 

        let oourl = sprintf "http://localhost/domain-types/%s" ooType
        let parms =  new JObject (new JProperty(ooRel,  new JObject(new JProperty(JsonPropertyNames.Value, new JObject(new JProperty(JsonPropertyNames.Href, oourl))))))
        let parmsEncoded = HttpUtility.UrlEncode(parms.ToString())

        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel (parms.ToString())

        let args = CreateArgMap parms

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        
        VerifyResult result resultValue oType oRel ooType ooRel

let GetIsSuperTypeOfReturnFalseFormalParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.MostSimple"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSupertypeOf"
        let ooRel = JsonPropertyNames.SubType
        let resultValue = false;
        let oourl = sprintf "http://localhost/domain-types/%s" ooType
        let parms =  new JObject (new JProperty(ooRel,  new JObject(new JProperty(JsonPropertyNames.Value, new JObject(new JProperty(JsonPropertyNames.Href, oourl))))))
        let parmsEncoded = HttpUtility.UrlEncode(parms.ToString())

        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel (parms.ToString())

        let args = CreateArgMap parms

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        VerifyResult result resultValue oType oRel ooType ooRel
 
let GetIsSubTypeOfReturnTrueFormalParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.WithActionObject"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSubtypeOf"
        let ooRel = JsonPropertyNames.SuperType
        let resultValue = true
        let oourl = sprintf "http://localhost/domain-types/%s" ooType
        let parms =  new JObject (new JProperty(ooRel,  new JObject(new JProperty(JsonPropertyNames.Value, new JObject(new JProperty(JsonPropertyNames.Href, oourl))))))
        let parmsEncoded = HttpUtility.UrlEncode(parms.ToString())

        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel (parms.ToString())

        let args = CreateArgMap parms

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        VerifyResult result resultValue oType oRel ooType ooRel
 
let GetIsSuperTypeOfReturnTrueFormalParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.WithAction"
        let ooType = ttc "RestfulObjects.Test.Data.WithActionObject"
        let oRel = "isSupertypeOf"
        let ooRel = JsonPropertyNames.SubType
        let resultValue = true
        let oourl = sprintf "http://localhost/domain-types/%s" ooType
        let parms =  new JObject (new JProperty(ooRel,  new JObject(new JProperty(JsonPropertyNames.Value, new JObject(new JProperty(JsonPropertyNames.Href, oourl))))))
        let parmsEncoded = HttpUtility.UrlEncode(parms.ToString())

        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel (parms.ToString())

        let args = CreateArgMap parms

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        VerifyResult result resultValue oType oRel ooType ooRel

let NotFoundTypeIsSubTypeOfSimpleParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.NoSuchType"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSubtypeOf"
        let ooRel = JsonPropertyNames.SuperType
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs

        let args = CreateArgMapFromUrl qs

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
        
        Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode)
        Assert.AreEqual(sprintf "199 RestfulObjects \"No such domain type %s\"" oType, result.Headers.Warning.ToString())
        Assert.AreEqual("", jsonResult)

let NotFoundTypeIsSuperTypeOfSimpleParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.NoSuchType"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSupertypeOf"
        let ooRel = JsonPropertyNames.SubType
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs

        let args = CreateArgMapFromUrl qs

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
        
        Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode)
        Assert.AreEqual(sprintf "199 RestfulObjects \"No such domain type %s\"" oType, result.Headers.Warning.ToString())
        Assert.AreEqual("", jsonResult)

let NotFoundTypeIsSubTypeOfFormalParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.NoSuchType"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSubtypeOf"
        let ooRel = JsonPropertyNames.SuperType
        let oourl = sprintf "http://localhost/domain-types/%s" ooType
        let parms =  new JObject (new JProperty(ooRel,  new JObject(new JProperty(JsonPropertyNames.Value, new JObject(new JProperty(JsonPropertyNames.Href, oourl))))))
        let parmsEncoded = HttpUtility.UrlEncode(parms.ToString())
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel parmsEncoded

        let args = CreateArgMap parms

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
        
        Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode)
        Assert.AreEqual(sprintf "199 RestfulObjects \"No such domain type %s\"" oType, result.Headers.Warning.ToString())
        Assert.AreEqual("", jsonResult)

let NotFoundTypeIsSuperTypeOfFormalParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.NoSuchType"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSupertypeOf"
        let ooRel = JsonPropertyNames.SubType
        let oourl = sprintf "http://localhost/domain-types/%s" ooType
        let parms =  new JObject (new JProperty(ooRel,  new JObject(new JProperty(JsonPropertyNames.Value, new JObject(new JProperty(JsonPropertyNames.Href, oourl))))))
        let parmsEncoded = HttpUtility.UrlEncode(parms.ToString())
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel parmsEncoded

        let args = CreateArgMap parms

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
        
        Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode)
        Assert.AreEqual(sprintf "199 RestfulObjects \"No such domain type %s\"" oType, result.Headers.Warning.ToString())
        Assert.AreEqual("", jsonResult)

let NotFoundActionSimpleParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.MostSimple"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "noSuchAction"
        let ooRel = JsonPropertyNames.SuperType
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs 

        let args = CreateArgMapFromUrl qs

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
        
        Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode)
        Assert.AreEqual(sprintf "199 RestfulObjects \"No such domain type action noSuchAction in domain type %s\"" oType, result.Headers.Warning.ToString())
        Assert.AreEqual("", jsonResult)

let NotFoundActionFormalParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.MostSimple"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "noSuchAction"
        let ooRel = JsonPropertyNames.SuperType
        let oourl = sprintf "http://localhost/domain-types/%s" ooType
        let parms =  new JObject (new JProperty(ooRel,  new JObject(new JProperty(JsonPropertyNames.Value, new JObject(new JProperty(JsonPropertyNames.Href, oourl))))))
        let parmsEncoded = HttpUtility.UrlEncode(parms.ToString())
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel parmsEncoded

        let args = CreateArgMap parms
        
        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
        
        Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode)
        Assert.AreEqual(sprintf "199 RestfulObjects \"No such domain type action noSuchAction in domain type %s\"" oType, result.Headers.Warning.ToString())
        Assert.AreEqual("", jsonResult)

let NotFoundSuperTypeIsSubTypeOfSimpleParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.WithAction"
        let ooType = ttc "RestfulObjects.Test.Data.NoSuchType"
        let oRel = "isSubtypeOf"
        let ooRel = JsonPropertyNames.SuperType
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs

        let args = CreateArgMapFromUrl qs

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
        
        Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode)
        Assert.AreEqual(sprintf "199 RestfulObjects \"No such domain type %s\"" ooType, result.Headers.Warning.ToString())
        Assert.AreEqual("", jsonResult)

let NotFoundSubTypeIsSuperTypeOfSimpleParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.WithAction"
        let ooType = ttc "RestfulObjects.Test.Data.NoSuchType"
        let oRel = "isSupertypeOf"
        let ooRel = JsonPropertyNames.SubType
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs

        let args = CreateArgMapFromUrl qs

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
       
        Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode)
        Assert.AreEqual(sprintf "199 RestfulObjects \"No such domain type %s\"" ooType, result.Headers.Warning.ToString())
        Assert.AreEqual("", jsonResult)

let NotFoundSuperTypeIsSubTypeOfFormalParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.WithAction"
        let ooType = ttc "RestfulObjects.Test.Data.NoSuchType"
        let oRel = "isSubtypeOf"
        let ooRel = JsonPropertyNames.SuperType
        let oourl = sprintf "http://localhost/domain-types/%s" ooType
        let parms =  new JObject (new JProperty(ooRel,  new JObject(new JProperty(JsonPropertyNames.Value, new JObject(new JProperty(JsonPropertyNames.Href, oourl))))))
        let parmsEncoded = HttpUtility.UrlEncode(parms.ToString())
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel parmsEncoded

        let args = CreateArgMap parms
        
        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
        
        Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode)
        Assert.AreEqual(sprintf "199 RestfulObjects \"No such domain type %s\"" ooType, result.Headers.Warning.ToString())
        Assert.AreEqual("", jsonResult)

let NotFoundSubTypeIsSuperTypeOfFormalParms(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.WithAction"
        let ooType = ttc "RestfulObjects.Test.Data.NoSuchType"
        let oRel = "isSupertypeOf"
        let ooRel = JsonPropertyNames.SubType
        let oourl = sprintf "http://localhost/domain-types/%s" ooType
        let parms =  new JObject (new JProperty(ooRel,  new JObject(new JProperty(JsonPropertyNames.Value, new JObject(new JProperty(JsonPropertyNames.Href, oourl))))))
        let parmsEncoded = HttpUtility.UrlEncode(parms.ToString())
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel parmsEncoded

        let args = CreateArgMap parms

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
        
        Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode)
        Assert.AreEqual(sprintf "199 RestfulObjects \"No such domain type %s\"" ooType, result.Headers.Warning.ToString())
        Assert.AreEqual("", jsonResult)

        // not acceptable 

let MissingParmsIsSubTypeOf(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.MostSimple"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSubtypeOf"
        let ooRel = JsonPropertyNames.SuperType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke" oType oRel 

        let args = CreateArgMapFromUrl ""

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
       
        Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode)
        Assert.AreEqual("199 RestfulObjects \"Missing arguments\"", result.Headers.Warning.First().ToString())
        Assert.AreEqual("", jsonResult)

let MalformedSimpleParmsIsSubTypeOf(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.MostSimple"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSubtypeOf"
        let ooRel = "nosuchtype"
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs

        let args = CreateArgMapFromUrl qs

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
        
        Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode)
        Assert.AreEqual("199 RestfulObjects \"Malformed arguments\"", result.Headers.Warning.First().ToString())
        Assert.AreEqual("", jsonResult)

let MalformedFormalParmsIsSubTypeOf(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.MostSimple"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSubtypeOf"
        let ooRel = "nosuchtype"

        let oourl = sprintf "http://localhost/domain-types/%s" ooType
        let parms =  new JObject (new JProperty(ooRel,  new JObject(new JProperty(JsonPropertyNames.Value, new JObject(new JProperty(JsonPropertyNames.Href, oourl))))))
        let parmsEncoded = HttpUtility.UrlEncode(parms.ToString())

        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel parmsEncoded 

        let args = CreateArgMap parms

        api.Request <- jsonGetMsg(url)
        let result = api.GetInvokeIsTypeOf(oType, oRel, args)
        let jsonResult = readSnapshotToJson result
     
        Assert.AreEqual(HttpStatusCode.BadRequest, result.StatusCode)
        Assert.AreEqual("199 RestfulObjects \"Malformed arguments\"", result.Headers.Warning.First().ToString())
        Assert.AreEqual("", jsonResult)

let NotAcceptableIsSubTypeOf(api : RestfulObjectsControllerBase) = 
        let oType = ttc "RestfulObjects.Test.Data.MostSimple"
        let ooType = ttc "RestfulObjects.Test.Data.WithAction"
        let oRel = "isSubtypeOf"
        let ooRel = JsonPropertyNames.SuperType
        let qs = sprintf "%s=%s" ooRel ooType
        let url = sprintf "http://localhost/domain-types/%s/type-actions/%s/invoke?%s" oType oRel qs

        try 
            let args = CreateArgMapFromUrl qs
            let msg = jsonGetMsg(url)
            msg.Headers.Accept.Single().Parameters.Add(new NameValueHeaderValue ("profile", (makeProfile RepresentationTypes.ActionDescription)))
            api.Request <- msg
            let result = api.GetInvokeIsTypeOf(oType, oRel, args)
            let jsonResult = readSnapshotToJson result
            Assert.Fail("expect exception")
        with 
            | :? HttpResponseException as ex -> Assert.AreEqual(HttpStatusCode.NotAcceptable, ex.Response.StatusCode)